查看原文
其他

如何用好缓存?全面梳理(第二篇)

TomGE 微观技术 2022-03-15


缓存系列文章,接上一篇




既然本地缓存有这么多的不足,那能不能把缓存独立出来呢?统一化管理。分布式缓存借助分布式的理念,采用集群化部署,突破单机的容量限制,理论上支持无限扩容。如果数据更新了,只需要调整对应的数据节点分片,不像本地缓存那样,要同时维护很多套副本数据,数据的一致性维护成本比较低。并且容易配备很多服务治理工具,提升系统的高可用、稳定性。支持独立运维。做到专业的人做专业的事。



任何事情都有其两面性,将缓存从应用服务器中剥离出来。需要跨服务器走网络传输。所以分布式缓存的不足:网络传输带来的性能损耗


网络传输的损耗 ~1ms。比起优点,这点损耗微不足道。




旁路缓存策略。可能存在极低概率并发问题!一种场景。


两个线程并发写:A、B线程。变更数据库和变更缓存是两个独立的操作,而我们并没有对操作做任何的并发控制。那么当两个线程并发更新它们的时候,就会因为写入顺序的不同造成数据的不一致。解决:更新数据时不更新缓存,而是删除缓存中的数据。在读取数据时,来触发预热填充。


可以采用类似于juc中的ReadWriteLock,读写锁来控制并发,但是性能会比较差。最好的方式还是设置缓存的过期时间。


Cache Aside 策略是我们日常开发中最经常使用的缓存策略,不过我们在使用时也要根据实际场景,灵活应变。



Cache Aside 维护两套数据存储:缓存、数据库。需要上层控制一致性。


我们经常使用的分布式缓存组件, Memcached 、 Redis 都不提供写入数据库,或者自动加载数据库中的数据的功能。


本地缓存,大量使用这种策略,如:Guava  Cache 中的 Loading Cache,预留扩展接口,我们只需要实现CacheLoader接口,如果缓冲没有该数据kv对,则自动调用接口方法获取。


Write Through 策略中写数据库是同步的,对于性能有比较大的开销。



操作系统层面的page cache就是采用这种思想。就是操作系统在内存中给磁盘上的文件建立的缓存。在调用系统的 API 读写文件的时候,并不会直接去读写磁盘上的文件,应用程序实际操作的都是 PageCache,也就是文件在内存中缓存的副本。


Kafka 的吞吐量很高,具体原因?


  • 使用批量消息提升服务端处理能力

  • 使用顺序读写提升磁盘 IO 性能

  • ZeroCopy:零拷贝技术

  • 是利用了 PageCache 的特性。一般来说,消息刚刚写入到MQ server端就会被消费,按照 LRU 的“优先清除最近最少使用的页”这种策略,消费端拉取消息时,对于这种刚刚写入的 PageCache,命中的几率会非常高。也就是说,大部分情况下,consumer端拉取消息都会命中 PageCache,带来的好处有两个:一个是读取的速度会非常快,另外一个是,给写入消息让出磁盘的 IO 资源,间接也提升了写入的性能。


业务:计数器、扣减库存,也可以考虑使用这种策略,多次请求合并。



有 Cache 的地方就必然存在失效问题。保证数据的一致性。


单一的缓存节点受到机器内存、网卡带宽和单节点请求量的限制,不能承担比较高的并发,因此我们考虑将数据分片,每个节点上存储部分数据。客户端按一定的路由策略将请求打到不同的数据节点上。


1、余数hash分片。对缓存的key做哈希计算,然后对总的缓存节点数取余,得到目标分片节点。属于最常规的路由策略。缺点:如果缓存空间不足,要扩容或者缩容,会造成大量的缓存key失效。


2、一致性哈希算法。将整个 Hash 值空间组织成一个虚拟的圆环,然后将缓存节点的 IP 地址或者主机名做 Hash 取值后,放置在这个圆环上。当我们要计算某一个 Key 需要路由到哪个节点上的时候,先对这个 Key 做同样的 Hash 取值,确定在环上的位置,然后按照顺时针方向在环上查找,遇到的第一个缓存节点就是要访问的节点。在增加和删除节点时,只有少量的 Key 会“漂移”到其它节点上,大部分的 Key 命中的节点还是会保持不变。可以有效解决因扩容问题带来的大量的缓存失效。


缺点:缓存节点在圆环上分布不平均,会造成部分缓存节点的压力较大;当某个节点故障时,这个节点所要承担的所有访问都会被顺移到另一个节点上,会对后面这个节点造成压力,如果流量水位较高时,很容易压垮,进而引发连锁反应,集群挂掉。


3、一致性哈希改进。它将一个缓存节点计算多个 Hash 值分散到圆环的不同位置,这样实现了数据的平均,而且当某一个节点故障或者退出的时候,它原先承担的 Key 将以更加平均的方式分配到其他节点上。


4、区间算法。Redis cluster,哈希槽,16384,3个节点,(0, 5500)(5501, 11000)(11001,16383),HASH_SLOT = CRC16(key) mod 16384



缓存适用的业务场景非常多,这里简单罗列了一些。



全文共三篇,未完待续。。。



往期推荐


关注【微观技术】


我们热衷于收集&分享高并发、系统架构、微服务、消息中间件、 RPC框架、高性能缓存、搜索、分布式数据框架、分布式协同服务、分布式配置中心、中台架构、领域驱动设计、系统监控、系统稳定性等技术知识。

关注公众号,后台回复“中台,下载PDF学习资料


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存